package com.alibaba.citrus.cr.mn.order.center.facade.service.impl;

import com.alibaba.citrus.cr.b2b.trade.order.facade.common.SetOrderTag;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.enums.ordercenter.AsyncMessageEventEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderCategoryEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.SalesOrderPushStatusEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.SalesOrderTypeEnum;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.common.lock.SaleRedisLock;
import com.alibaba.citrus.cr.mn.order.center.common.util.AssertUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.TrimUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.function.common.*;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.mnordercenter.model.dto.*;
import com.epoch.app.mnordercenter.orderbaserequest.*;
import com.epoch.app.mnordercenter.salesorderatom.dto.SapModifyCallbackRequest;
import com.epoch.app.mnordercenter.salesorderatom.dto.SapRefuseCallbackRequest;
import com.epoch.app.mnordercenter.salesorderatom.service.SalesOrderAtomService;
import com.google.common.collect.Lists;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.alibaba.citrus.cr.mn.order.center.common.constants.RedisLockConstants.*;

/**
 * @auther dongju.fyj
 * @date 2023/4/19
 */
@Primary
@Component
public class SalesOrderAtomServiceImpl implements SalesOrderAtomService {

    private static final Log log = Log.getLogger(SalesOrderAtomServiceImpl.class);

    @Resource(name = "salesOrderAtomCreateService")
    private OrderAtomCreateService salesOrderAtomCreateService;
    @Resource(name = "salesOrderAtomUpdateService")
    private OrderAtomUpdateService salesOrderAtomUpdateService;
    @Resource(name ="salesOrderAtomCloseService")
    private OrderAtomCloseService salesOrderAtomCloseService;
    @Resource(name = "salesOrderAtomSubmitService")
    private OrderAtomSubmitService salesOrderAtomSubmitService;
    @Resource(name = "salesOrderAtomCancelService")
    private OrderAtomCancelService selesOrderAtomCancelService;
    @Resource(name="salesOrderAtomQueryService")
    private OrderAtomQueryService salesOrderAtomQueryService;
    @Resource
    private SendMsgService sendMsgService;

    @FacadeInvoker(value = "销售订单批量创建", errorCode = "OC-01-001-01-16-006")
    @Override
    public Result<List<SalesOrderAtomCreateResponse>> batchCreate(SalesOrderAtomBatchCreateRequest request) {
        log.info("SalesOrderAtomServiceImpl#batchCreate request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_ATOM_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("SalesOrderAtomServiceImpl#batchCreate lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderAtomServiceImpl#batchCreate 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            // 移除入参里的前后空格
            TrimUtils.removeSpace(request);

            // 销售订单创建服务 +  SAP创单消息发送
            List<OrderAtomCreateResponse> resp = salesOrderAtomCreateService.batchCreate(request.getOrderList());
            List<SalesOrderAtomCreateResponse> result = new ArrayList<>();
            for (OrderAtomCreateResponse x : resp) {
                SalesOrderAtomCreateResponse response = new SalesOrderAtomCreateResponse();
                BeanUtils.copyProperties(x, response);
                result.add(response);
            }
            List<SalesOrderAtomCreateResponse> failList = result.stream().filter(p -> StringUtils.isNotBlank(p.getErrorCode())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(failList)) {
                return Result.fail(result, "OC-01-001-01-16-006", "销售订单批量创建失败");
            }
            return Result.success(result, "", "");
        } catch (Exception e) {
            log.error("SalesOrderAtomServiceImpl#batchCreate error", e);
            throw e;
        }
    }

    @FacadeInvoker(value = "销售订单批量提交", errorCode = "OC-01-003-01-16-002")
    @Override
    public Result<List<OrderAtomSubmitResponse>> batchSubmit(OrderAtomBatchSubmitRequest request) {
        log.info("SalesOrderAtomServiceImpl#batchSubmit request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_ATOM_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("SalesOrderAtomServiceImpl#batchSubmit lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderAtomServiceImpl#batchSubmit 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            // 销售订单提交服务 +  SAP创单消息发送
            List<OrderAtomSubmitRequest> orderList = request.getOrderList();
            List<OrderAtomSubmitResponse> submitResponses = salesOrderAtomSubmitService.batchSubmit(orderList);
            if (CollectionUtils.isNotEmpty(submitResponses)) {
                // 发送消息通知来源系统
                List<PushOrderInfoToMnSideRequestOrderInfo> pushOrderInfoList = new ArrayList<>();
                for (OrderAtomSubmitResponse submitResponse : submitResponses) {
                    pushOrderInfoList.add(PushOrderInfoToMnSideRequestOrderInfo.builder()
                            .salesOrderNo(submitResponse.getSalesOrderNo())
                            .orderStatus(SalesOrderPushStatusEnum.FAIL_UPDATE.getOrderStatusCode())
                            .message(submitResponse.getMessage())
                            .build());
                }
                // 发送kafka消息通知应用端处理结果
//                sendMsgService.sendMsgToNYK(pushOrderInfoList);
                CommonAsyncMessageResponse commonAsyncMessageResponse = new CommonAsyncMessageResponse();
                commonAsyncMessageResponse.setEventCode(AsyncMessageEventEnum.SALES_ORDER_UPDATE.getValue());
                commonAsyncMessageResponse.setEventName(AsyncMessageEventEnum.SALES_ORDER_UPDATE.getLabel());
                commonAsyncMessageResponse.setEventTime(String.valueOf(new Date().getTime()));
                commonAsyncMessageResponse.setFromSys(request.getOrderList().get(0).getFromSys());
                commonAsyncMessageResponse.setBusinessUnitCode(request.getOrderList().get(0).getBusinessUnitCode());
                commonAsyncMessageResponse.setData(pushOrderInfoList);
                sendMsgService.sendMsgToSendKafka(commonAsyncMessageResponse);
                log.info("SalesOrderAtomServiceImpl#batchSubmit sendMsgToSendKafka message={}", commonAsyncMessageResponse);
            }
            return Result.success(Lists.newArrayList(), "", "");
        } catch (Exception e) {
            log.error("SalesOrderAtomServiceImpl#batchSubmit error", e);
            throw e;
        }
    }

    @FacadeInvoker(value = "销售订单批量关闭", errorCode = "OC-01-003-01-16-003")
    @Override
    public Result<List<OrderAtomCloseResponse>> batchClose(OrderAtomBatchCloseRequest request) {
        log.info("SalesOrderAtomServiceImpl#batchClose request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_ATOM_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("SalesOrderAtomServiceImpl#batchClose lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderAtomServiceImpl#batchClose 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }

            List<OrderAtomCloseResponse> closeResponses = salesOrderAtomCloseService.batchClose(request);
            if (CollectionUtils.isNotEmpty(closeResponses)) {
                // 发送消息通知来源系统
                List<PushOrderInfoToMnSideRequestOrderInfo> pushOrderInfoList = new ArrayList<>();
                for (OrderAtomCloseResponse closeResponse : closeResponses) {
                    if (Boolean.TRUE.equals(closeResponse.getSuccess())) {
                        // 成功的不发kafka消息，要基于sap关闭回调结果发kafka消息
                        continue;
                    }
                    pushOrderInfoList.add(PushOrderInfoToMnSideRequestOrderInfo.builder()
                            .salesOrderNo(closeResponse.getSalesOrderNo())
                            .lineNum(closeResponse.getLineNum())
                            .orderStatus(SalesOrderPushStatusEnum.FAIL_REFUSED.getOrderStatusCode())
                            .message(closeResponse.getMessage())
                            .build());
                }
                // 发送kafka消息通知应用端处理结果
//                sendMsgService.sendMsgToNYK(pushOrderInfoList);
                CommonAsyncMessageResponse commonAsyncMessageResponse = new CommonAsyncMessageResponse();
                commonAsyncMessageResponse.setEventCode(AsyncMessageEventEnum.SALES_ORDER_REFUSED.getValue());
                commonAsyncMessageResponse.setEventName(AsyncMessageEventEnum.SALES_ORDER_REFUSED.getLabel());
                commonAsyncMessageResponse.setEventTime(String.valueOf(new Date().getTime()));
                commonAsyncMessageResponse.setFromSys(request.getOrderList().get(0).getFromSys());
                commonAsyncMessageResponse.setBusinessUnitCode(request.getOrderList().get(0).getBusinessUnitCode());
                commonAsyncMessageResponse.setData(pushOrderInfoList);
                sendMsgService.sendMsgToSendKafka(commonAsyncMessageResponse);
                log.info("SalesOrderAtomServiceImpl#batchClose sendMsgToSendKafka message={}", commonAsyncMessageResponse);
            }
        } catch (Exception e) {
            log.error("SalesOrderAtomServiceImpl#batchClose error", e);
            throw e;
        }
        return Result.success(Lists.newArrayList(), "", "");
    }

    /**
     * 精准查询
     */
    @FacadeInvoker(value = "订单精准查询", errorCode = "OC-01-003-01-16-008")
    @Override
    public Result<List<SalesOrderAtomQueryResponse>> loadListForPage(SalesOrderAtomQueryListRequest salesOrderAtomQueryListRequest) {
        PageResult<List<SalesOrderAtomQueryResponse>> result = salesOrderAtomQueryService.listPage(salesOrderAtomQueryListRequest);
        List<SalesOrderAtomQueryResponse> salesOrderAtomQueryResponseList = result.getContent();
        if (CollectionUtils.isNotEmpty(salesOrderAtomQueryResponseList)) {
            salesOrderAtomQueryResponseList.parallelStream().forEach(salesOrderAtomQueryResponse -> {
                salesOrderAtomQueryResponse.setRelatonNo(null);
                salesOrderAtomQueryResponse.setReceiveStatus(null);
                salesOrderAtomQueryResponse.setDeliveryFactoryCode(null);
                salesOrderAtomQueryResponse.setOrderChannelName(null);
                salesOrderAtomQueryResponse.setCustomerGroup(null);
                salesOrderAtomQueryResponse.setStockCode(null);
                salesOrderAtomQueryResponse.setDeliveryFactoryName(null);
                salesOrderAtomQueryResponse.setReceiveWarehouseName(null);
                salesOrderAtomQueryResponse.setReceiveStockCode(null);
                salesOrderAtomQueryResponse.setReceiveFactoryName(null);
                salesOrderAtomQueryResponse.setReceiveWarehouseCode(null);
                salesOrderAtomQueryResponse.setOrderCategoryName(null);
                salesOrderAtomQueryResponse.setStockName(null);
                salesOrderAtomQueryResponse.setReceiveFactoryCode(null);
                salesOrderAtomQueryResponse.setReceiveStockName(null);
                salesOrderAtomQueryResponse.setCustomerGrade(null);
                List<SalesOrderAtomQueryDetailResponse> salesOrderAtomQueryDetailResponseList = salesOrderAtomQueryResponse.getOrderDetails();
                salesOrderAtomQueryDetailResponseList.parallelStream().forEach(salesOrderAtomQueryDetailResponse -> {
                    salesOrderAtomQueryDetailResponse.setReceiveStatus(null);
                    salesOrderAtomQueryDetailResponse.setProduceDate(null);
                    salesOrderAtomQueryDetailResponse.setGiftQuantity(null);
                    salesOrderAtomQueryDetailResponse.setTotalActivityFee(null);
                    salesOrderAtomQueryDetailResponse.setTaxRate(null);
                    salesOrderAtomQueryDetailResponse.setFromSys(null);
                    salesOrderAtomQueryDetailResponse.setCumulativeReceivedQuantity(null);
                });
            });
        }
        Result<List<SalesOrderAtomQueryResponse>> success = Result.success(salesOrderAtomQueryResponseList, "", "");
        success.setTotal(result.getTotal());
        return success;
    }

    /**
     * 批量查询
     */
    @FacadeInvoker(value = "订单批量查询", errorCode = "OC-01-003-01-16-008")
    @Override
    public Result<List<SalesOrderAtomQueryResponse>> loadForPage(SalesOrderAtomPageQueryRequest request) {
        // 校验销售订单的单据类型
        List<String> salesOrderType = request.getSalesOrderType();
        if (CollectionUtils.isEmpty(salesOrderType)) {
            request.setSalesOrderType(SalesOrderTypeEnum.companyOrderCodes());
        } else {
            salesOrderType.forEach(tmpSalesOrderCode -> {
                if (Objects.isNull(SalesOrderTypeEnum.of(tmpSalesOrderCode))) {
                    throw new FunctionException("OC-01-001-01-15-006", "订单类型编码");
                }
            });
        }
        if (StringUtils.isBlank(request.getOrderCategoryCode())) {
            request.setOrderCategoryCodeList(Lists.newArrayList(OrderCategoryEnum.COMPANY.getCode(), OrderCategoryEnum.STOCK.getCode()));
        } else {
            AssertUtils.lengthCheck(request.getOrderCategoryCode(), 50, false, "OC-01-001-01-15-004", "订单类别编码");
            AssertUtils.isTrue(!Lists.newArrayList(OrderCategoryEnum.COMPANY.getCode(), OrderCategoryEnum.STOCK.getCode()).contains(request.getOrderCategoryCode()), "OC-01-001-01-15-006", "订单类别编码");
        }
        PageResult<List<SalesOrderAtomQueryResponse>> result = salesOrderAtomQueryService.page(request, SetOrderTag.NORMAL);
        result.getContent().forEach(order -> {
            order.setDeliveryFactoryCode(null);
            order.setOrderChannelName(null);
            order.setCustomerGroup(null);
            order.setStockCode(null);
            order.setDeliveryFactoryName(null);
            order.setCustomerGroupName(null);
            order.setReceiveWarehouseName(null);
            order.setReceiveFactoryName(null);
            order.setReceiveStockCode(null);
            order.setReceiveWarehouseCode(null);
            order.setOrderCategoryName(null);
            order.setStockName(null);
            order.setReceiveFactoryCode(null);
            order.setReceiveStockName(null);
            order.setCustomerGrade(null);
            order.setOrderDetails(null);
        });
        Result<List<SalesOrderAtomQueryResponse>> success = Result.success(result.getContent(), "", "");
        success.setTotal(result.getTotal());
        return success;
    }

    @FacadeInvoker(value = "SAP销售订单拒绝回调", errorCode = "OC-01-003-01-16-001")
    @Override
    public Result<Void> sapRefuseCallback(SapRefuseCallbackRequest request) {
        log.info("SalesOrderAtomServiceImpl#sapRefuseCallback request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_ATOM_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("SalesOrderAtomServiceImpl#sapRefuseCallback lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderAtomServiceImpl#sapRefuseCallback 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }
            salesOrderAtomCloseService.refuseCallback(request);
        } catch (Exception e) {
            log.error("SalesOrderAtomServiceImpl#sapRefuseCallback error", e);
            throw e;
        }
        return Result.success(null, "", "");
    }

    @FacadeInvoker(value = "SAP销售订单修改回调", errorCode = "OC-01-003-01-16-001")
    @Override
    public Result<Void> sapModifyCallback(SapModifyCallbackRequest request) {
        log.info("SalesOrderAtomServiceImpl#sapModifyCallback request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_ATOM_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("SalesOrderAtomServiceImpl#sapModifyCallback lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderAtomServiceImpl#sapModifyCallback 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }
            salesOrderAtomUpdateService.modifyCallback(request);
        } catch (Exception e) {
            log.error("SalesOrderAtomServiceImpl#sapModifyCallback error", e);
            throw e;
        }
        return Result.success(null, "", "");
    }


    @FacadeInvoker(value = "销售订单批量取消", errorCode = "OC-01-003-01-16-009")
    @Override
    public Result<List<OrderAtomCancelResponse>> batchCancel(OrderAtomBatchCancelRequest request) {
        log.info("SalesOrderAtomServiceImpl#batchCancel request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_ATOM_PREFIX + DigestUtils.md5Hex(JSON.toJSONString(request));
        log.info("SalesOrderAtomServiceImpl#batchCancel lockKey={}", lockKey);

        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderAtomServiceImpl#batchCancel 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }
            List<OrderAtomCancelResponse> resp= selesOrderAtomCancelService.batchCancel(request);
            return Result.success(resp, "", "");
        } catch (Exception e) {
            log.error("SalesOrderAtomServiceImpl#batchCancel error", e);
            throw e;
        }
    }

    @FacadeInvoker(value = "更新销售订单", errorCode = "OC-01-001-01-16-013")
    @Override
    public Result<OrderAtomUpdateResponse> update(OrderAtomUpdateRequest request) {
        log.info("SalesOrderAtomServiceImpl#update request={}", JSON.toJSONString(request));
        String lockKey = SALES_ORDER_ATOM_PREFIX + request.getSalesOrderNo();
        log.info("SalesOrderAtomServiceImpl#update lockKey={}", lockKey);
        try (SaleRedisLock lock = new SaleRedisLock(CACHE_CODE, lockKey, TIMEOUT_MSECS, EXPIRE_MSECS, SLEEP_MILLIS)) {
            if (!lock.lock()) {
                log.error("SalesOrderAtomServiceImpl#update 分布式锁获取失败 lockKey={}", lockKey);
                return Result.fail("OC-00-000-01-99-002", "分布式锁获取失败");
            }
            OrderAtomUpdateResponse response = salesOrderAtomUpdateService.update(request);
            if(StringUtils.isNotBlank(response.getErrorCode())){
                return Result.fail(response.getErrorCode(), response.getMessage());
            }
            return Result.success(response, "", "");
        } catch (Exception e) {
            log.error("SalesOrderAtomServiceImpl#update error", e);
            throw e;
        }
    }


}
